import CryptoJS from 'crypto-js'

/***
 * 解密
 * @params word 解密内容
 *  okey 密钥
 * 	oiv 密钥偏移量
 */
export const Decrypt = (word:string, okey:string,oiv:string) =>{
	let key = CryptoJS.enc.Utf8.parse(okey);  //十六位十六进制数作为密钥
	let iv = CryptoJS.enc.Utf8.parse(oiv);   //十六位十六进制数作为密钥偏移量
  if(!word) return
    let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
    let srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
    let decrypt = CryptoJS.AES.decrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
    let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    return decryptedStr.toString();
}

/**
 *  加密
 * @params word 加密内容
 *  okey 密钥
 * 	oiv 密钥偏移量
 */
export const Encrypt = (word:string,okey:string,oiv:string) =>{
	let key = CryptoJS.enc.Utf8.parse(okey);  //十六位十六进制数作为密钥
	let iv = CryptoJS.enc.Utf8.parse(oiv);   //十六位十六进制数作为密钥偏移量
  if(!word) return
    let srcs = CryptoJS.enc.Utf8.parse(word);
    let encrypted = CryptoJS.AES.encrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
    return encrypted.ciphertext.toString().toUpperCase();
}

/**
 * 获取本地图片 
 * @params logoName 图片名字
 */
export const getImgUrl = (logoName: string) => {
  let url = '/src/assets/'
  return url + logoName
}
/**
 * URL解析 参数
 * @params
 */


/**
 * 拼接URL
 * @params
 */

/**
 * URL解析 
 * @params
 */


 // 判断是否为数组
/*
  * funname:isArray
  * des:判断是否为数组
  * params: [array] arr
  * return: [bolean]
  */
export const isArray = (arr: Array<any>) => {
    if (typeof arr === 'object' && arr.constructor == Array) {
        return true;
    }
    return false;
}
/**验证不能包含字母
 * @param { string } value
 */
export const isNoWord = (value:string) => /^[^A-Za-z]*$/g.test(value);

/**
 * 验证中文和数字
 * @param { string } value
 */
export const isCHNAndEN = (value:string) => /^((?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])|(\d))+$/g.test(value);

/**
 * 验证16进制颜色
 * @param { string } value
 */
export const isColor16 = (value:string) => /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/g.test(value);

/**
 * 验证统一社会信用代码
 *  @param { string } value
 */
export const isCreditCode = (value:string) => /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/g.test(value);

/**
 * 验证英文姓名
 * @param { string } value
 */
export const isEnglishName = (value:string) => /(^[a-zA-Z]{1}[a-zA-Z\s]{0,20}[a-zA-Z]{1}$)/g.test(value);

/**
 * 验证车牌号(新能源+非新能源)
 * @param { string } value
 */
export const isLicensePlateNumber = (value:string) => /^(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}(?:(?:[0-9]{5}[DF])|(?:[DF](?:[A-HJ-NP-Z0-9])[0-9]{4})))|(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9 挂学警港澳]{1})$/g.test(value);

/**
 * 验证手机号 严谨
 * @param { string } value
 */
export const isMPStrict = (value:string) => /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-7|9])|(?:5[0-3|5-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1|8|9]))\d{8}$/g.test(value);

/**
 * 验证email(邮箱)
 * @param { string } value
 */
export const isEmail = (value:string) => /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/g.test(value);


/**
 * 验证身份证号 1+2代
 * @param { string } value
 */
export const isIDCard = (value:string)  => /(^\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(^\d{6}(18|19|20)\d{2}(0\d|10|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)$)/g.test(value);

/**
 * 验证帐号是否合法(字母开头，允许5-16字节，允许字母数字下划线组合
 * @param { string } value
 */
export const isWebAccount = (value:string)  => /^[a-zA-Z]\w{4,15}$/g.test(value);

/**
 * 验证小数
 * @param { string } value
 */
export const isDecimal = (value:string)  => /^\d+\.\d+$/g.test(value);

/**
 * 验证数字
 * @param { string } value
 */
export const isNumber = (value:string) => /^\d{1,}$/g.test(value);

/**
 * 获取窗口可视范围的高度
 */
export function getClientHeight() {
	let clientHeight = 0;
	if (document.body.clientHeight && document.documentElement.clientHeight) {
			clientHeight = (document.body.clientHeight < document.documentElement.clientHeight) ? document.body.clientHeight : document.documentElement.clientHeight;
	}
	else {
			clientHeight = (document.body.clientHeight > document.documentElement.clientHeight) ? document.body.clientHeight : document.documentElement.clientHeight;
	}
	return clientHeight;
}

/**
 * 获取滚动条距顶部高度
 */
export function getPageScrollTop() {
	let a = document;
	return a.documentElement.scrollTop || a.body.scrollTop;
}
/**
 * 返回当前滚动条位置
 */
export const getScrollPosition = (el = window) => ({
	x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
	y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
});

/**
 * 目前对象值如果是函数 、RegExp等特殊对象存贮会被忽略
 * @param { String } key  属性
 * @param { string } value 值
 */
export const localStorageSet = (key: string, value:any) => {
	if (typeof (value) === 'object') value = JSON.stringify(value);
	localStorage.setItem(key, value)
};
/**
 * @param {String} key  属性
 */
export const localStorageGet = (key: string) => {
	return localStorage.getItem(key)
};

/**
 * 金额格式化
 *  @param { number } num
 */
export const formatMoney = (num:number|string) => num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");

/**
 * 截取字符串并加身略号
 */
export function subText(str:any, length:string) {
	if (str.length === 0) {
			return '';
	}
	if (str.length > length) {
			return str.substr(0, length) + "...";
	} else {
			return str;
	}
}

/**
 * @param file
 * @param format  指定文件格式
 * @param size  指定文件大小(字节)
 * @param formatMsg 格式错误提示
 * @param sizeMsg   大小超出限制提示
 * @returns {Promise<any>}
 */
 export function fileToBase64String(file:any, format = ['jpg', 'jpeg', 'png', 'gif'], size = 20 * 1024 * 1024, formatMsg = '文件格式不正确', sizeMsg = '文件大小超出限制') {
	return new Promise((resolve, reject) => {
			// 格式过滤
			let suffix = file.type.split('/')[1].toLowerCase();
			let inFormat = false;
			for (let i = 0; i < format.length; i++) {
					if (suffix === format[i]) {
							inFormat = true;
							break;
					}
			}
			if (!inFormat) {
					reject(formatMsg);
			}
			// 大小过滤
			if (file.size > size) {
					reject(sizeMsg);
			}
			// 转base64字符串
			let fileReader = new FileReader();
			fileReader.readAsDataURL(file);
			fileReader.onload = () => {
					let res = fileReader.result;
					resolve({base64String: res, suffix: suffix});
					reject('异常文件，请重新选择');
			}
	})
}
/**
 * base64转file
 *  @param { base64 } base64
 *  @param { string } filename 转换后的文件名
 */
export const base64ToFile = (base64:any, filename:string )=> {
	let arr = base64.split(',');
	let mime = arr[0].match(/:(.*?);/)[1];
	let suffix = mime.split('/')[1] ;// 图片后缀
	let bstr = atob(arr[1]);
	let n = bstr.length;
	let u8arr = new Uint8Array(n);
	while (n--) {
			u8arr[n] = bstr.charCodeAt(n)
	}
	return new File([u8arr], `${filename}.${suffix}`, { type: mime })
};

/**
 * 判断手机是Andoird还是IOS
 *  0: ios
 *  1: android
 *  2: 其它
 */
export function getOSType() {
	let u = navigator.userAgent, app = navigator.appVersion;
	let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1;
	let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
	if (isIOS) {
			return 0;
	}
	if (isAndroid) {
			return 1;
	}
	return 2;
}

/**
 * 防抖
 * @param { function } func
 * @param { number } wait 延迟执行毫秒数
 * @param { boolean } immediate  true 表立即执行，false 表非立即执行
 */
export function debounce(func:Function,wait:number,immediate:boolean) {
	let timeout:any;
	return function () {
			let context = this;
			let args = arguments;

			if (timeout) clearTimeout(timeout);
			if (immediate) {
					let callNow = !timeout;
					timeout = setTimeout(() => {
							timeout = null;
					}, wait);
					if (callNow) func.apply(context, args)
			}
			else {
					timeout = setTimeout(() => {
							func.apply(context, args)
					}, wait);
			}
	}
}
/**
 * 节流
 * @param { function } func 函数
 * @param { number } wait 延迟执行毫秒数
 * @param { number } type 1 表时间戳版，2 表定时器版
 */
export function throttle(func: Function, wait: number ,type:number) {
	let previous:any, timeout:any;
	if(type===1){
			previous = 0;
	}else if(type===2){
			timeout = null;
	}
	return function() {
			let context = this;
			let args = arguments;
			if(type===1){
					let now = Date.now();

					if (now - previous > wait) {
							func.apply(context, args);
							previous = now;
					}
			}else if(type===2){
					if (!timeout) {
							timeout = setTimeout(() => {
									timeout = null;
									func.apply(context, args)
							}, wait)
					}
			}

	}
}
/**
 * 生成指定范围随机数
 * @param { number } min 
 * @param { number } max 
 */
 export const RandomNum = (min:number, max:number) => Math.floor(Math.random() * (max - min + 1)) + min;

/**
 * 加法函数（精度丢失问题）
 * @param { number } arg1
 * @param { number } arg2
 */
export function add(arg1:number, arg2:number) {
	let r1, r2, m;
	try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
	try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
	m = Math.pow(10, Math.max(r1, r2));
	return (arg1 * m + arg2 * m) / m
}

/**
 * 减法函数（精度丢失问题）
 * @param { number } arg1
 * @param { number } arg2
 */
export function sub(arg1:number, arg2:number) {
	let r1, r2, m, n;
	try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }
	try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }
	m = Math.pow(10, Math.max(r1, r2));
	n = (r1 >= r2) ? r1 : r2;
	return Number(((arg1 * m - arg2 * m) / m).toFixed(n));
}
/**
 * 除法函数（精度丢失问题）
 * @param { number } num1
 * @param { number } num2
 */
export function division(num1:number,num2:number){
	let t1,t2,r1,r2;
	try{
			t1 = num1.toString().split('.')[1].length;
	}catch(e){
			t1 = 0;
	}
	try{
			t2=num2.toString().split(".")[1].length;
	}catch(e){
			t2=0;
	}
	r1=Number(num1.toString().replace(".",""));
	r2=Number(num2.toString().replace(".",""));
	return (r1/r2)*Math.pow(10,t2-t1);
}
/**
 * 乘法函数（精度丢失问题）
 * @param { number } num1
 * @param { number } num2
 */
export function mcl(num1:number,num2:number){
	let m=0,s1=num1.toString(),s2=num2.toString();
	try{m+=s1.split(".")[1].length}catch(e){}
	try{m+=s2.split(".")[1].length}catch(e){}
	return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);
}

/**
 * 去除空格
 * @param { string } str 待处理字符串
 * @param  { number } type 去除空格类型 1-所有空格  2-前后空格  3-前空格 4-后空格 默认为1
 */
export function trim(str:string, type:number = 1) {
	if (type && type !== 1 && type !== 2 && type !== 3 && type !== 4) return;
	switch (type) {
			case 1:
					return str.replace(/\s/g, "");
			case 2:
					return str.replace(/(^\s)|(\s*$)/g, "");
			case 3:
					return str.replace(/(^\s)/g, "");
			case 4:
					return str.replace(/(\s$)/g, "");
			default:
					return str;
	}
}

/**
 * 数字超过规定大小加上加号“+”，如数字超过99显示99+
 * @param { number } val 输入的数字
 * @param { number } maxNum 数字规定界限
 */
export const outOfNum = (val:number, maxNum:number) =>{
	val = val ? val-0 :0;
	if (val > maxNum ) {
			return `${maxNum}+`
	}else{
			return val;
	}
};

/**
 * 手机号脱敏
 *  @param { string } mobile 输入的数字
 */
export const hideMobile = (mobile:string) => {
  return mobile.replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2")
}
/**
 * 数组对象根据字段去重
 * @param { Array } arr 要去重的数组
 * @param { string } key 根据去重的字段名
 */
export const uniqueArrayObject = (arr:Array<any> = [], key:string = 'id') => {
  if (arr.length === 0) return
  let list = []
  const map:any = {}
  arr.forEach((item) => {
    if (!map[item[key]]) {
      map[item[key]] = item
    }
  })
  list = Object.values(map)

  return list
}